﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Axe.Collections
{
    public delegate TOut ConversionDelegate<TIn, TOut>(TIn input);

    public static class EnumeratorAdapter
    {
        public static TOut DerivedConverter<TIn, TOut>(TIn input)
            where TIn:TOut
        {
            return input;
        }

        public static EnumeratorAdapter<TIn, TOut> Create<TIn, TOut>(IEnumerable<TIn> input)
            where TIn:TOut
        {
            return new EnumeratorAdapter<TIn,TOut>(
                input, 
                new ConversionDelegate<TIn,TOut>( DerivedConverter<TIn,TOut> ));
        }
    }

    public class EnumeratorAdapter<TIn, TOut> : IEnumerator<TOut>, IEnumerable<TOut>
    {
        readonly ConversionDelegate<TIn, TOut> m_Converter;
        IEnumerator<TIn> m_Source;

        public EnumeratorAdapter(IEnumerable<TIn> inp, ConversionDelegate<TIn, TOut> converter)
        {
            m_Converter = converter;
            m_Source = inp.GetEnumerator();
        }

        public EnumeratorAdapter(IEnumerator<TIn> inp, ConversionDelegate<TIn,TOut> converter)
        {
            m_Converter = converter;
            m_Source = inp;
        }


        #region IEnumerator<TOut> Members

        public TOut Current
        {
            get { return m_Converter( m_Source.Current ); }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            m_Source.Dispose();
        }

        #endregion

        #region IEnumerator Members

        object System.Collections.IEnumerator.Current
        {
            get { return m_Source.Current; }
        }

        public bool MoveNext()
        {
            return m_Source.MoveNext();
        }

        public void Reset()
        {
            m_Source.Reset();
        }

        #endregion

        #region IEnumerable<TOut> Members

        public IEnumerator<TOut> GetEnumerator()
        {
            return this;
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this;
        }

        #endregion
    }
}
